package com.app.business.calculate;

import com.app.business.en.HouseType;
import com.app.business.model.*;
import com.app.business.service.*;
import com.app.business.utils.AreaAndPriceUtils;
import com.app.business.utils.CalculateDate;
import com.app.system.permission.service.DataDictService;
import com.app.system.utils.ApplicationContextProvider;
import com.app.system.utils.CollectionUtils;
import com.app.system.utils.dataType.BigDecimalUtils;
import com.app.system.utils.dataType.IntegerUtils;
import com.google.common.collect.Maps;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 计算方法
 * Created by ZYK on 2019/2/28.
 */
public class CalculateUtils {

    private static ContractService contractService;
    private static OverAreaPriceNewService overAreaPriceNewService;
    private static HouseService houseService;
    private static StorageRoomService storageRoomService;
    private static CarLotService carLotService;
    private static DataDictService dataDictService;
    private static AdjustAreaService adjustAreaService;
    private static ShopHouseService shopHouseService;


    /**
     * 自动计算
     * 接受一个对象，对此对象的方案补助款分别计算
     *
     * @param contractId
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    public synchronized static void main(Integer contractId) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
        contractService = (ContractService) applicationContext.getBean(ContractService.class);
        houseService = (HouseService) applicationContext.getBean(HouseService.class);
        storageRoomService = (StorageRoomService) applicationContext.getBean(StorageRoomService.class);
        carLotService = (CarLotService) applicationContext.getBean(CarLotService.class);
        dataDictService = (DataDictService) applicationContext.getBean(DataDictService.class);
        overAreaPriceNewService = (OverAreaPriceNewService) applicationContext.getBean(OverAreaPriceNewService.class);
        adjustAreaService = (AdjustAreaService) applicationContext.getBean(AdjustAreaService.class);
        shopHouseService = (ShopHouseService) applicationContext.getBean(ShopHouseService.class);
        List<AdjustArea> adjustAreaList = adjustAreaService.getAdjustAreaListByContractId(contractId);
        Contract contract = contractService.findOne(contractId);
        if (contract == null || contract.getZsProject() == null) {
            return;
        }
        //以下计算：正数代表：被征收人应领取的金额；负数代表：被征收人应补缴的金额
        contract = calArea(contract);
        System.out.println("房源、储物间面积计算完成！");
        contract = calKkgArea(contract);
        System.out.println("可扩改建筑面积、金额计算完成！");
        contract = calMoney(contract);
        System.out.println("房源、储物间购房款计算完成！");
        if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
            contract = calSyArea(contract);
            System.out.println("未结算剩余面积已计算！");

        }
        /*若属于石狮市宝盖镇前坑村(回批地安置A5、C3、C4、C5、C14地块)选房安置征收项目 id = 8 则不计算楼层补差*/

        contract = calLctJMoney(contract);
        System.out.println("楼层调节补偿补差金额计算");
        contract = calCarLotMoney(contract);
        System.out.println("车位计算完成！");
        contract = calBzMoney(contract);
        System.out.println("过渡费计算完成！");
        contract = calWxMoney(contract);
        System.out.println("专项维修基金计算完成！");
        contract = calOtherMoney(contract,adjustAreaList);
        System.out.println("其他费用计算完成！");
        contract = calTaxMoney(contract);
        System.out.println("房源费用计算完成！");
        contractService.save(contract);
        System.out.println("************************计算完成！************************");
    }

    /**
     * 计算房源的面积、数量
     *
     * @param contract
     * @return
     */
    private static Contract calArea(Contract contract) {
        //选择的普通型房源数量、选择的小户型房源数量、房源总数
        Integer normalHouseNum = 0, smallHouseNum = 0, fsHouseNum = 0, houseNum = 0;
        //选择的普通型房源面积、选择的小户型房源面积、房源总面积
        BigDecimal normalHouseArea = BigDecimal.ZERO, smallHouseArea = BigDecimal.ZERO, fsHouseArea = BigDecimal.ZERO, chooseHouseAreaTotal = BigDecimal.ZERO;
        //选房期房、现房面积分别多少
        BigDecimal chooseHouseQiFangAreaTotal = BigDecimal.ZERO, chooseHouseXianFangAreaTotal = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());

        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                if (house.getHouseType() == null) {
                    continue;
                }
                //普通型
                if (house.getHouseType().equals(HouseType.NORMAL.getIndex())) {
                    normalHouseNum++;
                    normalHouseArea = BigDecimalUtils.getSum(normalHouseArea, house.getBuildArea());
                } else if (house.getHouseType().equals(HouseType.SMALL.getIndex())) {   //小户型（单身公寓）
                    smallHouseNum++;
                    smallHouseArea = BigDecimalUtils.getSum(smallHouseArea, house.getBuildArea());
                } else if (house.getHouseType().equals(HouseType.FS.getIndex())) {   //复式
                    fsHouseNum++;
                    fsHouseArea = BigDecimalUtils.getSum(fsHouseArea, house.getBuildArea());
                }
            }
            houseNum = IntegerUtils.getSum(normalHouseNum, smallHouseNum, fsHouseNum);   //房源总数量
            chooseHouseAreaTotal = BigDecimalUtils.getSum(normalHouseArea, smallHouseArea, fsHouseArea);   //房源总面积
        }
        //获取已选现房房源
        List<House> houseNature1List = houseService.getHouseListByContractIdAndHouseNature1(contract.getId());
        //获取已选期房房源
        List<House> houseNature2List = houseService.getHouseListByContractIdAndHouseNature2(contract.getId());

        BigDecimal houseNature1Area = BigDecimal.ZERO;
        BigDecimal houseNature2Area = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(houseNature1List)) {
            for (House house : houseNature1List) {
                houseNature1Area = BigDecimalUtils.getSum(houseNature1Area, house.getBuildArea());
            }
        }
        if (CollectionUtils.isNotEmpty(houseNature2List)) {
            for (House house : houseNature2List) {
                houseNature2Area = BigDecimalUtils.getSum(houseNature2Area, house.getBuildArea());
            }
        }

        //店铺情况面积 2024年5月5日 店面用于置换即店面总价值/6500元
        List<ShopHouse> shopHouseList = shopHouseService.getShopHouseListByContractId(contract.getId());

        Integer shopHouseNum = 0;  //店铺数量
        BigDecimal shopHouseArea = BigDecimal.ZERO; //店铺面积
        BigDecimal dmResultArea = BigDecimal.ZERO;//店面面积（抵扣后最终店面面积：用于计算）
        if (CollectionUtils.isNotEmpty(shopHouseList)) {
            for (ShopHouse shopHouse : shopHouseList) {
                shopHouseNum++;
                shopHouseArea = BigDecimalUtils.getSum(shopHouseArea,shopHouse.getBuildArea());
                dmResultArea = BigDecimalUtils.getSum(dmResultArea,shopHouse.getSxZhArea());
            }
        }

        contract.setShopHouseNum(shopHouseNum);
        contract.setShopHouseArea(shopHouseArea);
        contract.setDmResultArea(dmResultArea);//所需置换店面的面积
        contract.setNormalHouseNum(normalHouseNum);
        contract.setSmallHouseNum(smallHouseNum);
        contract.setNormalHouseArea(normalHouseArea);
        contract.setSmallHouseArea(smallHouseArea);
        contract.setHouseNum(houseNum);
        contract.setChooseHouseAreaTotal(chooseHouseAreaTotal);
        contract.setChooseHouseXianFangAreaTotal(houseNature1Area);
        contract.setChooseHouseQiFangAreaTotal(houseNature2Area);

        List<StorageRoom> storageRoomList = storageRoomService.getStorageRoomListByContractId(contract.getId());
        Integer storageRoomNum = 0;  //储物间数量
        //储物间面积
        BigDecimal storageRoomArea = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(storageRoomList)) {
            for (StorageRoom storageRoom : storageRoomList) {
                storageRoomNum++;
                storageRoomArea = BigDecimalUtils.getSum(storageRoomArea, storageRoom.getBuildArea());
            }
        }
        contract.setStorageRoomNum(storageRoomNum);
        contract.setStorageRoomArea(storageRoomArea);

        //住宅面积(不含储藏间)（抵扣后）、储藏间面积（抵扣后）
        BigDecimal zzResultArea = BigDecimal.ZERO, ccjResultArea = BigDecimal.ZERO;
        //若选房面积未超出执行以下计算，否则：可直接得出扩购面积、储物间面积
        if (contract.getLimitHouseAreaTotal().compareTo(chooseHouseAreaTotal) > 0) {
            //得到选房后还剩余的面积
            BigDecimal centerArea1 = BigDecimalUtils.getBigAndBigSub(contract.getLimitHouseAreaTotal(), chooseHouseAreaTotal);
            //得到所选储物间面积换算成产权面积后的面积
            BigDecimal centerArea2 = BigDecimalUtils.getBigAndBigDiv(storageRoomArea, contract.getParameter().getCwjBl(), 2);
            if (contract.getBuyStorageRoomType() != 2) {
                if (centerArea1.compareTo(centerArea2) >= 0) {
                    //如果剩余的面积 > 所选储物间面积换算成产权面积后的面积，那么不存在扩购，储物间面积也为0，得出产权减少的面积（负的）
                    zzResultArea = BigDecimalUtils.getBigAndBigSub(centerArea2, centerArea1);
                } else {
                    //否则，扩购面积为0，产权超出的面积*1.5即为，储物间换算后的面积
                    ccjResultArea = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigSub(centerArea2, centerArea1), contract.getParameter().getCwjBl()).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            } else {
                zzResultArea = BigDecimalUtils.getBigAndBigSub(chooseHouseAreaTotal, contract.getLimitHouseAreaTotal());
                ccjResultArea = storageRoomArea;
            }
        } else {
            zzResultArea = BigDecimalUtils.getBigAndBigSub(chooseHouseAreaTotal, contract.getLimitHouseAreaTotal());
            ccjResultArea = storageRoomArea;
        }
        contract.setZzResultArea(zzResultArea);
        contract.setCcjResultArea(ccjResultArea);
        return contract;
    }

    /**
     * 计算购房款
     *
     * @param contract
     * @return
     */
    private static Contract calMoney(Contract contract) {
        //房源购房款、储物间购房款
        BigDecimal houseMoney = BigDecimal.ZERO, storageRoomMoney = BigDecimal.ZERO;

        //判断选房面积是否超购
        if (contract.getZzResultArea().compareTo(BigDecimal.ZERO) <= 0) {
            //选房不足，购房款为正数（被征收人应领取金额），每平米3000元（每个项目可能不同）补偿
            houseMoney = BigDecimalUtils.getBigAndBigMul(contract.getZzResultArea(), contract.getParameter().getXfbcPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
            if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
                houseMoney = new BigDecimal("0");
            }
        } else {
            Map<String, Map> resultMap = overAreaPriceNewService.getOverHouseMoneyMap(contract);
            if (CollectionUtils.isNotEmpty(resultMap)) {
                Map itemMap = Maps.newHashMap();
                for (String str : resultMap.keySet()) {
                    itemMap = null;
                    itemMap = resultMap.get(str) == null ? Maps.newHashMap() : resultMap.get(str);
                    //循环取出每个面积段的购房款，如果为空或0，则为0，累加起来为总的需要缴的购房款
                    BigDecimal money = (itemMap.get("money") == null || itemMap.get("money").toString().equals("")) ? BigDecimal.ZERO : new BigDecimal(itemMap.get("money").toString());
                    houseMoney = BigDecimalUtils.getSum(houseMoney, money);
                }
            }
        }
        //储物间购房款 = 储物间面积(抵扣后) * 储物间申购单价 （为负数：被征收人应缴纳金额）
        storageRoomMoney = BigDecimalUtils.getBigAndBigMul(contract.getCcjResultArea(), contract.getParameter().getCwjPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        contract.setStorageRoomMoney(storageRoomMoney);
        contract.setHouseMoney(houseMoney);
        return contract;
    }

    /**
     * 计算车位数量、面积、价格
     *
     * @param contract
     * @return
     */
    private static Contract calCarLotMoney(Contract contract) {
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        Integer carLotNum = 0;  //车位数量
        BigDecimal carLotArea = BigDecimal.ZERO;   //车位面积
        BigDecimal carLotMoney = BigDecimal.ZERO;  //车位价格
        if (CollectionUtils.isNotEmpty(carLotList)) {
            carLotNum = 0;
            for (CarLot carLot : carLotList) {
                carLotNum++;
                carLotArea = BigDecimalUtils.getSum(carLotArea, carLot.getBuildArea());
                carLotMoney = BigDecimalUtils.getSum(carLotMoney, carLot.getPrice());
            }
        }

        contract.setCarLotArea(carLotArea);
        contract.setCarLotNum(carLotNum);
        contract.setCarLotMoney(carLotMoney.negate());   //（为负数：被征收人应缴纳金额）

        //现房车位
        List<CarLot> carLotXianFangList = carLotService.getCarLotListByContractIdAndHouseNature(contract.getId(), 1);
        BigDecimal carLotXianFangArea = BigDecimal.ZERO;
        BigDecimal carLotXianFangPrice = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(carLotXianFangList)) {
            for (CarLot carLot : carLotXianFangList) {
                carLotXianFangArea = BigDecimalUtils.getSum(carLotXianFangArea, carLot.getBuildArea());
                carLotXianFangPrice = BigDecimalUtils.getSum(carLotXianFangPrice, BigDecimalUtils.getNegateBig(carLot.getPrice()));
            }
        }
        contract.setCarLotXianFangArea(carLotXianFangArea);
        contract.setCarLotXianFangMoney(carLotXianFangPrice);
        //期房车位
        List<CarLot> carLotQiFangList = carLotService.getCarLotListByContractIdAndHouseNature(contract.getId(), 2);
        BigDecimal carLotQiFangArea = BigDecimal.ZERO;
        BigDecimal carLotQiFangPrice = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(carLotQiFangList)) {
            for (CarLot carLot : carLotQiFangList) {
                carLotQiFangArea = BigDecimalUtils.getSum(carLotQiFangArea, carLot.getBuildArea());
                carLotQiFangPrice = BigDecimalUtils.getSum(carLotQiFangPrice, BigDecimalUtils.getNegateBig(carLot.getPrice()));
            }
        }
        contract.setCarLotQiFangArea(carLotQiFangArea);
        contract.setCarLotQiFangMoney(carLotQiFangPrice);
        return contract;
    }

    /**
     * 计算住宅临时安置补助费
     */
    private static Contract calBzMoney(Contract contract) {
        BigDecimal zzbzMoney = BigDecimal.ZERO, zxbzMoney = BigDecimal.ZERO, bzMoneyTotal = BigDecimal.ZERO;
        //腾空日期，开始选房日期
        //自动计算
        if (contract.getIsDoubleMoney() != null && contract.getIsDoubleMoney() == 0) {
            int betweenMonth = CalculateDate.getDatesForMonth(contract.getTkDate(), contract.getChooseHouseDate());
            //住宅临时安置补助费
            if (betweenMonth > 36) {
                zzbzMoney = BigDecimalUtils.getBigAndBigMul(contract.getZzgdMoney(), new BigDecimal("2")).setScale(2, BigDecimal.ROUND_HALF_UP);   //发两个月的周转费
            } else {
                zzbzMoney = BigDecimalUtils.getNotNull(contract.getZzgdMoney()).setScale(2, BigDecimal.ROUND_HALF_UP);   //发一个月的周转费
            }
        }
        //手动计算
        else {
            //单倍
            if (contract.getIsDoubleMoney() != null && contract.getIsDoubleMoney() == 1) {
                zzbzMoney = BigDecimalUtils.getNotNull(contract.getZzgdMoney()).setScale(2, BigDecimal.ROUND_HALF_UP);   //发一个月的周转费
            }
            //双倍
            else if (contract.getIsDoubleMoney() != null && contract.getIsDoubleMoney() == 2) {
                zzbzMoney = BigDecimalUtils.getBigAndBigMul(contract.getZzgdMoney(), new BigDecimal("2")).setScale(2, BigDecimal.ROUND_HALF_UP);   //发两个月的周转费
            }
        }
        //装修补助费   =  每月应发的装修周转过渡费*3个月
        zxbzMoney = BigDecimalUtils.getBigAndBigMul(contract.getZxgdMoney(), new BigDecimal("3")).setScale(2, BigDecimal.ROUND_HALF_UP);

        bzMoneyTotal = BigDecimalUtils.getSum(zzbzMoney, zxbzMoney);

        contract.setZzbzMoney(zzbzMoney);
        contract.setZxbzMoney(zxbzMoney);
        contract.setBzMoneyTotal(bzMoneyTotal);
        return contract;
    }

    /**
     * 计算住宅专项维修基金
     *
     * @param contract
     * @return
     */
    private static Contract calWxMoney(Contract contract) {
        BigDecimal zzwxMoney = BigDecimal.ZERO, zzwxQiFangMoney = BigDecimal.ZERO, zzwxXianFangMoney = BigDecimal.ZERO,
                ccjwxMoney = BigDecimal.ZERO,
                cwwxMoney = BigDecimal.ZERO, cwwxXianFangMoney = BigDecimal.ZERO, cwwxQiFangMoney = BigDecimal.ZERO,
                dmwxMoney = BigDecimal.ZERO,
                wxMoneyTotal = BigDecimal.ZERO;
        //如果配置参数里住宅有本次缴交比例，则根据每套房的标准*比例累加，
        if (contract.getParameter().getGwjHouseNowBl() != null && contract.getParameter().getGwjHouseNowBl().compareTo(BigDecimal.ZERO) > 0) {
            List<House> houseList1 = houseService.getHouseListByContractIdAndHouseNature1(contract.getId());
            List<House> houseList2 = houseService.getHouseListByContractIdAndHouseNature2(contract.getId());
            if (CollectionUtils.isNotEmpty(houseList1)) {
                for (House house : houseList1) {
                    zzwxXianFangMoney = BigDecimalUtils.getSum(zzwxXianFangMoney,
                            BigDecimalUtils.getBigAndBigMul(house.getBuildArea(),
                                    BigDecimalUtils.getBigAndBigMul(house.getGwjPrice(), contract.getParameter().getGwjHouseNowBl())
                            )).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            }
            zzwxXianFangMoney = zzwxXianFangMoney.negate();
            if (CollectionUtils.isNotEmpty(houseList2)) {
                for (House house : houseList2) {
                    zzwxQiFangMoney = BigDecimalUtils.getSum(zzwxQiFangMoney,
                            BigDecimalUtils.getBigAndBigMul(house.getBuildArea(),
                                    BigDecimalUtils.getBigAndBigMul(house.getGwjPrice(), contract.getParameter().getGwjHouseNowBl())
                            )).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            }
            zzwxQiFangMoney = zzwxQiFangMoney.negate();

        } else {
            //否则，根据参数配置计算选房面积*参数配置中本次缴交总和
            //z住宅，期房、现房、合计
            zzwxQiFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getChooseHouseQiFangAreaTotal(), contract.getParameter().getZzbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
            zzwxXianFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getChooseHouseXianFangAreaTotal(), contract.getParameter().getZzbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();

        }
        zzwxMoney = BigDecimalUtils.getSum(zzwxQiFangMoney, zzwxXianFangMoney).setScale(2, BigDecimal.ROUND_HALF_UP);

        //储藏间
        ccjwxMoney = BigDecimalUtils.getBigAndBigMul(contract.getStorageRoomArea(), contract.getParameter().getCcjbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        dmwxMoney = BigDecimalUtils.getBigAndBigMul(contract.getShopHouseArea(), contract.getParameter().getDmwxPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
        //车位、期房、现房、合计
        cwwxXianFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getCarLotXianFangArea(), contract.getParameter().getCwbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        cwwxQiFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getCarLotQiFangArea(), contract.getParameter().getCwbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();

        cwwxMoney = BigDecimalUtils.getSum(cwwxXianFangMoney, cwwxQiFangMoney);

        //总合计
        wxMoneyTotal = BigDecimalUtils.getSum(zzwxMoney, ccjwxMoney, cwwxMoney);
        contract.setZzwxQiFangMoney(zzwxQiFangMoney);
        contract.setZzwxXianFangMoney(zzwxXianFangMoney);
        contract.setZzwxMoney(zzwxMoney);
        contract.setCcjwxMoney(ccjwxMoney);
        contract.setCwwxXianFangMoney(cwwxXianFangMoney);
        contract.setCwwxQiFangMoney(cwwxQiFangMoney);
        contract.setCwwxMoney(cwwxMoney);
        contract.setDmwxMoney(dmwxMoney);
        contract.setWxMoneyTotal(wxMoneyTotal);
        return contract;
    }

    /**
     * 计算其它相关费用以及汇总费用
     *
     * @param contract
     * @return
     */
    private static Contract calOtherMoney(Contract contract,List<AdjustArea> adjustAreaList) {
        BigDecimal finalMoney = BigDecimal.ZERO;
        BigDecimal houseFinalMoney = BigDecimal.ZERO;
        BigDecimal carLotFinalMoney = BigDecimal.ZERO;
        BigDecimal storageRoomFinalMoney = BigDecimal.ZERO;
        BigDecimal houseFinalNoWxjMoney = BigDecimal.ZERO;
        //前面几项累计 - 应缴交金额
        finalMoney = BigDecimalUtils.getSum(
                contract.getResultMoney(),   //应缴交金额
                contract.getHouseMoney(),   //购房款
                contract.getStorageRoomMoney(),   //购买储物间钱款
                contract.getCarLotMoney(),   //购买车位钱款
                contract.getBzMoneyTotal(),   //过渡补助金额
                contract.getWxMoneyTotal(),   //专项维修基金
                contract.getOtherMoney(),   //其它金额
                contract.getKkgHouseMoney(),   //可扩改面积应缴款
                contract.getTjMoneyTotal() //楼层调节应缴金额
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        houseFinalMoney = BigDecimalUtils.getSum(
                contract.getResultMoney(),   //应缴交金额
                contract.getHouseMoney(),   //购房款
                contract.getBzMoneyTotal(),   //过渡补助金额
                contract.getZzwxMoney(),   //住宅维修基金
                contract.getOtherMoney(),  //其它金额
                contract.getKkgHouseMoney(), //可扩改面积应缴款
                contract.getTjMoneyTotal() //楼层调节应缴金额
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        //合并金额加入进去
        if (CollectionUtils.isNotEmpty(adjustAreaList)) {
            for (AdjustArea adjustArea : adjustAreaList) {
                houseFinalMoney = BigDecimalUtils.getSum(
                        houseFinalMoney,
                        adjustArea.getHbGfk(),
                        adjustArea.getHbGdf()
                        ).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
        }

        houseFinalNoWxjMoney = BigDecimalUtils.getSum(
                contract.getResultMoney(),   //应缴交金额
                contract.getHouseMoney(),   //购房款
                contract.getBzMoneyTotal(),   //过渡补助金额
                contract.getOtherMoney(),  //其它金额
                contract.getKkgHouseMoney(), //可扩改面积应缴款
                contract.getTjMoneyTotal() //楼层调节应缴金额
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        //合并金额加入进去
        if (CollectionUtils.isNotEmpty(adjustAreaList)) {
            for (AdjustArea adjustArea : adjustAreaList) {
                houseFinalNoWxjMoney = BigDecimalUtils.getSum(
                        houseFinalNoWxjMoney,
                        adjustArea.getHbGfk(),
                        adjustArea.getHbGdf()
                ).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
        }

        carLotFinalMoney = BigDecimalUtils.getSum(
                contract.getCwwxMoney(),
                contract.getCarLotMoney()
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        storageRoomFinalMoney = BigDecimalUtils.getSum(
                contract.getCcjwxMoney(),
                contract.getStorageRoomMoney()
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        contract.setFinalMoney(finalMoney);
        contract.setHouseFinalMoney(houseFinalMoney);
        contract.setCarLotFinalMoney(carLotFinalMoney);
        contract.setStorageRoomFinalMoney(storageRoomFinalMoney);
        contract.setHouseFinalNoWxjMoney(houseFinalNoWxjMoney);
        return contract;
    }


    /**
     * 计算选房过后剩余产权调换和照顾购买面积
     *
     * @param contract
     * @return
     */
    private static Contract calSyArea(Contract contract) {
        BigDecimal sycqdhArea = BigDecimal.ZERO;
        BigDecimal syzggmArea = BigDecimal.ZERO;
        BigDecimal allChooseArea = contract.getChooseHouseAreaTotal();
        if (contract.getBuyStorageRoomType() != null && contract.getBuyStorageRoomType() == 1) {
            allChooseArea = BigDecimalUtils.getSum(contract.getChooseHouseAreaTotal(),
                    BigDecimalUtils.getBigAndBigDiv(contract.getStorageRoomArea(), contract.getParameter().getCwjBl(), 2));
        }
        if (contract.getPropertyChangeArea().compareTo(allChooseArea) >= 0) {
            sycqdhArea = BigDecimalUtils.getBigAndBigSub(contract.getPropertyChangeArea(), allChooseArea);
            syzggmArea = BigDecimalUtils.getSum(contract.getCareBuyArea1(), contract.getCareBuyArea2(), contract.getCareBuyArea3(), contract.getCareBuyArea4(),
                    contract.getCareBuyArea5(), contract.getCareBuyArea6(), contract.getCareBuyArea7());
        } else if (contract.getPropertyChangeArea().compareTo(allChooseArea) < 0) {
            syzggmArea = BigDecimalUtils.getBigAndBigSub(contract.getLimitHouseAreaTotal(), allChooseArea);
        }
        contract.setSycqdhArea(sycqdhArea.compareTo(new BigDecimal("0")) >= 0 ? sycqdhArea : new BigDecimal("0"));
        contract.setSyzggmArea(syzggmArea.compareTo(new BigDecimal("0")) >= 0 ? syzggmArea : new BigDecimal("0"));
        return contract;
    }

    /**
     * 计算房源的面积、数量
     *
     * @param contract
     * @return
     */
    private static Contract calKkgArea(Contract contract) {

        BigDecimal kkgHouseArea = BigDecimal.ZERO, kkgHouseMoney = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());

        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                kkgHouseArea = BigDecimalUtils.getSum(kkgHouseArea, house.getKkgArea());
            }
            kkgHouseMoney = BigDecimalUtils.getBigAndBigMul(kkgHouseArea, contract.getParameter().getKkgPrice()).negate();
        }
        contract.setKkgHouseArea(kkgHouseArea);
        contract.setKkgHouseMoney(kkgHouseMoney);
        return contract;
    }

    /**
     * 计算协议的的契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxMoney(Contract contract) {
        calTaxHouseMoney(contract);
        calTaxStorageMoney(contract);
        calTaxCarLotMoney(contract);
        //房源总应缴契税---车位储物间总应缴契税---总应缴契税
        BigDecimal taxHouseMoney = BigDecimal.ZERO, taxCarAndStorageMoney = BigDecimal.ZERO, taxMoney = BigDecimal.ZERO;
        //房源总应缴印花税---车位储物间总应缴印花税---总应缴印花税
        BigDecimal taxHouseYhsMoney = BigDecimal.ZERO, taxCarAndStorageYhsMoney = BigDecimal.ZERO, taxYhsMoney = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());
        List<StorageRoom> storageRoomList = storageRoomService.getStorageRoomListByContractId(contract.getId());
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        for (House house : houseList) {
            taxHouseMoney = BigDecimalUtils.getSum(taxHouseMoney, house.getTaxMoney());
            taxHouseYhsMoney = BigDecimalUtils.getSum(taxHouseYhsMoney, house.getTaxYhsMoney());
        }
        for (StorageRoom storageRoom : storageRoomList) {
            taxCarAndStorageMoney = BigDecimalUtils.getSum(taxCarAndStorageMoney, storageRoom.getTaxMoney());
            taxCarAndStorageYhsMoney = BigDecimalUtils.getSum(taxCarAndStorageYhsMoney, storageRoom.getTaxYhsMoney());
        }
        for (CarLot carLot : carLotList) {
            taxCarAndStorageMoney = BigDecimalUtils.getSum(taxCarAndStorageMoney, carLot.getTaxMoney());
            taxCarAndStorageYhsMoney = BigDecimalUtils.getSum(taxCarAndStorageYhsMoney, carLot.getTaxYhsMoney());
        }
        taxMoney = BigDecimalUtils.getSum(taxHouseMoney, taxCarAndStorageMoney);
        taxYhsMoney = BigDecimalUtils.getSum(taxHouseYhsMoney, taxCarAndStorageYhsMoney);

        contract.setTaxHouseMoney(taxHouseMoney);
        contract.setTaxCarAndStorageMoney(taxCarAndStorageMoney);
        contract.setTaxMoney(taxMoney);
        contract.setTaxHouseYhsMoney(taxHouseYhsMoney);
        contract.setTaxCarAndStorageYhsMoney(taxCarAndStorageYhsMoney);
        contract.setTaxYhsMoney(taxYhsMoney);
        contractService.save(contract);
        return contract;
    }

    /**
     * 计算房源的安置房金额、拆迁面积、拆迁补偿金额、契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxHouseMoney(Contract contract) {
        BigDecimal taxAzArea = BigDecimal.ZERO, taxAzAreaMoney = BigDecimal.ZERO, taxHouseMoney = BigDecimal.ZERO, taxMoney = BigDecimal.ZERO;
        BigDecimal price = BigDecimal.ZERO, area = BigDecimal.ZERO;
        BigDecimal allTaxAzArea = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());
        List<Map> mapList = AreaAndPriceUtils.getAreaAndPriceList(contract);
        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                taxAzArea = BigDecimal.ZERO;
                taxAzAreaMoney = BigDecimal.ZERO;
                taxHouseMoney = BigDecimal.ZERO;
                for (Map map : mapList) {
                    area = map.get("area") == null ? BigDecimal.ZERO : BigDecimalUtils.stringToBigDecimal(map.get("area").toString());
                    price = map.get("price") == null ? BigDecimal.ZERO : BigDecimalUtils.stringToBigDecimal(map.get("price").toString());
                    if (map.get("project").equals("产权调换面积")) {
                        //拆迁面积即使用产权调换面积taxAzArea
                        if (houseList.size() - 1 == houseList.indexOf(house)) {
                            taxAzArea = BigDecimalUtils.getBigAndBigSub(contract.getPropertyChangeArea(), allTaxAzArea);
                        } else {
                            taxAzArea = BigDecimalUtils.getBigAndBigMul(house.getBuildArea(), BigDecimalUtils.getBigAndBigDiv(area, contract.getChooseHouseAreaTotal(), 12)).setScale(11, BigDecimal.ROUND_HALF_UP);
                            allTaxAzArea = BigDecimalUtils.getSum(allTaxAzArea, taxAzArea);
                        }
                        //拆迁补偿金额，即使用产权调换部分taxAzArea*price
                        taxAzAreaMoney = BigDecimalUtils.getBigAndBigMul(taxAzArea, price);
                        house.setTaxAzArea(taxAzArea);
                        house.setTaxAzAreaMoney(taxAzAreaMoney);
                    }
                    //该部分比例----当前区间面积/总选房面积
                    //房产总价值----房源面积*当前使用该部分面积比例*单价
                    taxHouseMoney = BigDecimalUtils.getSum(taxHouseMoney, BigDecimalUtils.getBigAndBigMul(
                            BigDecimalUtils.getBigAndBigMul(house.getBuildArea(), BigDecimalUtils.getBigAndBigDiv(area, contract.getChooseHouseAreaTotal(), 12)).setScale(11, BigDecimal.ROUND_HALF_UP), price));

                    //契税---（房产总价值-拆迁面积）/1.05*0.03
                    taxMoney = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigDiv(BigDecimalUtils.getBigAndBigSub(taxHouseMoney, taxAzAreaMoney), new BigDecimal("1.05"), 10), new BigDecimal("0.03")).setScale(11, BigDecimal.ROUND_HALF_UP);

                    house.setTaxHouseMoney(taxHouseMoney);
                    house.setTaxMoney(taxMoney);
                    house.setTaxYhsMoney(BigDecimal.ZERO);
                    houseService.save(house);
                }
            }
        }
        return contract;
    }

    /**
     * 计算储物间的契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxStorageMoney(Contract contract) {
        BigDecimal storageMoney = BigDecimal.ZERO, taxStorageMoney = BigDecimal.ZERO, taxStorageYhsMoney = BigDecimal.ZERO;
        List<StorageRoom> storageRoomList = storageRoomService.getStorageRoomListByContractId(contract.getId());

        if (CollectionUtils.isNotEmpty(storageRoomList)) {
            for (StorageRoom storageRoom : storageRoomList) {
                //储物间房产价值----建筑面积*2000（默认使用购买）
                storageMoney = BigDecimalUtils.getBigAndBigMul(storageRoom.getBuildArea(), new BigDecimal("2000"));
                //储物间契税----储物间房产价值storageMoney/1.05*0.03
                taxStorageMoney = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigDiv(storageMoney, new BigDecimal("1.05"), 6), new BigDecimal("0.03"));
                //储物间印花税---储物间房产价值storageMoney*0.00025
                taxStorageYhsMoney = BigDecimalUtils.getBigAndBigMul(storageMoney, new BigDecimal("0.00025"));
                storageRoom.setTaxStorageMoney(storageMoney);
                storageRoom.setTaxMoney(taxStorageMoney);
                storageRoom.setTaxYhsMoney(taxStorageYhsMoney);
                storageRoomService.save(storageRoom);
            }
        }
        return contract;
    }

    /**
     * 计算车位的契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxCarLotMoney(Contract contract) {
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        BigDecimal taxCarLotMoney = BigDecimal.ZERO, taxCarLotYhsMoney = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(carLotList)) {
            for (CarLot carLot : carLotList) {
                //契税----车位价格price/1.05*0.03
                taxCarLotMoney = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigDiv(carLot.getPrice(), new BigDecimal("1.05"), 6), new BigDecimal("0.03"));
                //印花税---车位价格price*0.00025(2019-1-1后选房)
                taxCarLotYhsMoney = BigDecimalUtils.getBigAndBigMul(carLot.getPrice(), new BigDecimal("0.00025"));
                carLot.setTaxMoney(taxCarLotMoney);
                carLot.setTaxYhsMoney(taxCarLotYhsMoney);
                carLotService.save(carLot);
            }
        }
        return contract;
    }

    /**
     * 楼层调节补差金额
     * @param contract
     * @return
     */
    private static Contract calLctJMoney(Contract contract) {
        calTaxHouseMoney(contract);
        calTaxStorageMoney(contract);
        calTaxCarLotMoney(contract);

        BigDecimal tjMoneyTotal = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());
        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                tjMoneyTotal = BigDecimalUtils.getSum(tjMoneyTotal,house.getTjMoney());
            }
        }
        if (contract.getZsProject().getId() == 8) {
            tjMoneyTotal = BigDecimal.ZERO;
        }
        contract.setTjMoneyTotal(BigDecimalUtils.getBigAndBigSub(BigDecimal.ZERO,tjMoneyTotal));//需要缴纳的钱需要转为负数
        contractService.save(contract);
        return contract;
    }

}
